Pointer Chain

전통적인 책임 사슬의 구현 방법
class CreatureModifier{
CreatureModifier* next{nullptr};
protected:
Creature& creature; // , ,
public:
explicit CreatureModifier(Creature& creature): creature(creature) {}
void add(CreatureMoifier* cm){
if(next) next->add(cm);
else next=cm;
}
virtual void handle(){
if(next) next->handle(); //
}
};
handle은 재귀적으로 동작을 수행하도록 구현되어 있다.
(위의 handle은 어떠한 작업도 하지 않기 때문에 virtual로 정의해 둠, 단순 사슬 연결용)

위 CreatureModifier는 연결 리스트에 항목을 추가하는 기능밖에는 특별한 기능이 없지만,
이 클래스를 상속해 실질적인 작업을 시작하면 구현의 의미가 명확해진다.
class DoubleAttackModifier: public CreatureModifier{
public:
explicit DoubleAttackModifier(Creature& creature): CreatureModifier(creature) {}
void handle() override {
creature.attack*=2; //
CreatureModifier::handle(); // handle( )
}
};
class IncreaseDefenseModifier: public CreatureModifier{
public:
explicit IncreaseDefenseModifier(Creature& creature): CreatureModifier(creature) {}
void handle() override {
if(creature.attack<=2) creature.defense+=1;
CreatureModifier::handle();
}
};
//
Creature goblin{"Goblin", 1, 1};
CreatureModifier root{goblin};
DoubleAttackModifier r1{goblin};
DoubleAttackModifier r1_2{goblin};
IncreaseDefenseModifier r2{goblin};
root.add(&r1);
root.add(&r1_1);
root.add(&r2);
root.handle();
cout<<goblin<<endl;
위의 클래스들이 담고 있는 creature 변수는 실제 객체가 아닌 포인터, 참조 등임

next->handle()을 통해서 자식 클래스에서 재정의(override)된 handle() 메서드를 수행
중간 클래스의 handle()에서 부모 클래스의 handle()을 막아서, next 클래스들에 정의된 handle() 수행을
제어할 수 있다.
class NoBonusesModifier: public CreatureModifier{
public:
explicit NoBonuseseModifier(Creature& creature): CreatureModifier(creature) {}
void handle() override {
// do nothing next handle()
}
};
// NoBonusesModifier